#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Time    : 2018/4/16 11:16
# @Author  : simple0426
# @Email   : istyle.simple@gmail.com
# @File    : istyle_mail.py
# @Software: PyCharm
# @desc    : 此脚本主要用于发送邮件，可发送对象：文本、附件、正文图片

from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.header import Header
from email.utils import parseaddr, formataddr
from email import encoders
import smtplib
import os

class Mail(object):
    """
    1. 支持的发送对象：文字、图片[正文]、附件
    2. 默认发送文字，附件发送类型为“file”，图片发送类型为“image”
    3. 收件人为多个时应当写为列表
    3. 使用范例：
        mail = Mail('13200000000@163.com', '******', 'smtp.163.com', port=25, ssl=False)
        mail.bind_obj('正文测试2')
        mail.bind_obj('simple.png', 'image')
        mail.bind_obj('hf.txt', 'file')
        mail.sendmail('主题', '收件人')
    """
    msg = MIMEMultipart()
    CID = 0

    # 初始化对象时传入发件人邮件、密码、邮箱服务器
    def __init__(self, from_addr, password, smtp_server, smtp_port=25, ssl=False):
        self.from_addr = from_addr
        self.password = password
        self.smtp_server = smtp_server
        self.smtp_port = smtp_port
        self.ssl = ssl
        self._executed = None

    # 定义需要添加的文件或图片对象
    def file_obj(self, msg, msg_type):
        f = open(msg, 'rb')
        filename = os.path.basename(msg)
        main_obj = MIMEBase('application', 'octet-stream')
        if msg_type == 'file':
            main_obj.add_header('Content-Disposition', 'attachment', filename=filename)
        elif msg_type == 'image':
            self.CID = self.CID + 1
            html_body = """
            <html>
            <body>
            <p><img src="cid:%s"></p>
            </body>
            </html>
            """ % self.CID
            image_obj = MIMEText(html_body, 'html', 'utf-8')
            self.msg.attach(image_obj)
            main_obj.add_header('Content-ID', ('%s' % self.CID))
        main_obj.set_payload(f.read())
        encoders.encode_base64(main_obj)
        f.close()
        return main_obj

    # 根据用户输入添加指定的邮件对象
    def bind_obj(self, msg, msg_type='html'):
        main_obj = None
        if msg_type in ['html', 'plain']:
            main_obj = MIMEText(msg, 'html', 'utf-8')
            self.msg.attach(main_obj)
        elif msg_type == 'file' and os.path.exists(msg):
            main_obj = self.file_obj(msg, 'file')
            self.msg.attach(main_obj)
        elif msg_type == 'image' and os.path.exists(msg):
            main_obj = self.file_obj(msg, 'image')
            self.msg.attach(main_obj)
        else:
            pass
        self._executed = main_obj
        return self.msg

    # 邮件头部处理方法
    @staticmethod
    def _format_addr(s):
        name, addr = parseaddr(s)
        return formataddr((Header(name, 'utf-8').encode(), addr))

    # 邮件发送行为
    def sendmail(self, subject, receiver):
        # 收件人处理
        if isinstance(receiver, str):
            # str to list
            self.receiver = receiver.split()
        elif isinstance(receiver, list):
            self.receiver = receiver
        else:
            raise ValueError
        # 头部处理
        self.msg['From'] = self._format_addr('Python爱好者 <%s>' % self.from_addr)
        self.msg['Subject'] = Header(subject, 'utf-8').encode()
        # 添加主体
        if self._executed:
            # 登陆邮件服务器并发送
            if self.ssl:
                server = smtplib.SMTP_SSL(self.smtp_server, self.smtp_port)
            else:
                server = smtplib.SMTP(self.smtp_server, self.smtp_port)
            server.login(self.from_addr, self.password)
            server.sendmail(self.from_addr, self.receiver, self.msg.as_string())
            server.quit()
        else:
            raise PermissionError('exec bind_obj first')

